home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 3983 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  4.0 KB

  1. Path: dawn.mmm.com!news
  2. From: kjhopps@mmm.com (Kevin J Hopps)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Copy constructing an already default constructed object
  5. Date: 26 Jan 1996 23:08:13 GMT
  6. Organization: 3M - St. Paul, MN  55144-1000 US
  7. Message-ID: <4ebmst$7cl@dawn.mmm.com>
  8. References: <4e906b$stk@elaine32.Stanford.EDU> <4eal0n$hgq@dawn.mmm.com> <3108ef14.340699@nntp>
  9. Reply-To: kjhopps@mmm.com
  10. X-Newsreader: TIN [version 1.2 PL2]
  11.  
  12. brien oberstein (brien@leland.stanford.edu) wrote:
  13. > On 26 Jan 1996 13:29:59 GMT, kjhopps@mmm.com (Kevin J Hopps) wrote:
  14.  
  15. [ example elided ]
  16.  
  17. > >First, you have to decide for yourself what the copy semantics of
  18. > >your class are -- deep or shallow.  Regardless of what you decide,
  19. > >I think that the copy constructor and the assignment operator
  20. > >should produce identical results.  Frequently one is written in
  21. > >terms of the other.  Ultimately they must do an exhaustive copy
  22. > >of each data member.  Using memcpy as above can overwrite
  23. > >compiler-generated data within the object and can have unpredictable
  24. > >results.
  25. > <snip>
  26.  
  27. > What compiler generated data?  The vtable pointer?  What if I'm not
  28. > using virtual functions?
  29.  
  30. If you're using virtual functions memcpy is definitely bad.  If you're
  31. not, I don't know whether it is guaranteed to work or not.
  32.  
  33. > Ok.  Lemme give a better example of the actual problem I'm having.
  34. > The object I have has other objects within it (which allocate
  35. > dynamically), but no pointers are contained _directly_ in its class.
  36.  
  37. If you do not specify a copy constructor, one will be provided for
  38. you.  By default, it does a *memberwise* (not bitwise) copy.
  39.  
  40. > class A{
  41. > public:
  42. >     A();
  43. >     A(const A&);
  44. >     A(char *);
  45.  
  46. > private:
  47. >    B b0, b1;
  48. > };
  49.  
  50. For this class, a memberwise copy would be sufficient, assuming
  51. that copying B's does what you want.  (If B is a class, it must
  52. either have a copy constructor, or perform correctly with memberwise
  53. copying.  If B is a pointer, you might have problems.)  So, you
  54. don't need to specify a copy constructor for A.  (FWIW, I always
  55. do anyway, for completeness and to show the reader that I haven't
  56. forgotten about copying.)
  57.  
  58. > class B{
  59. > public:
  60. >   B();
  61. >   B(const B&);
  62. >   B(char *);
  63.  
  64. > private:
  65. >    char *p;
  66. > }
  67.  
  68. If you want "deep copy" semantics for B, you must provide a
  69. copy constructor here unless you want copied B's to share the
  70. same pointers.
  71.  
  72. > So my copy constructor for A is easy:
  73. > A::A(const A& other) : b0(other.b0), b1(other.b1) { }
  74.  
  75. > Now how do you do the copy?  Do you have to
  76. > overload = for all the contained operators too?
  77. > ie,
  78.  
  79. The rule for the assignment operator is the same as the
  80. rule for the copy constructor.  If memberwise assignment
  81. works, then you don't need to provide an assignment
  82. operator.
  83.  
  84. I'm not sure what you mean by "contained operators."  If
  85. you are asking whether you need to overload operator= for
  86. member objects, the answer is the same -- you need to
  87. overload operator= if memberwise assignment is not what
  88. you want.
  89.  
  90. > A::operator =(const A& other)
  91. > {
  92. >   b0 = other.b0 ;
  93. >   b1 = other.b1;
  94. > }
  95.  
  96. Be sure to check for (this != &other).
  97.  
  98. > To me this seems like a major pain in the butt.  All I really
  99. > want to do is have the copy constructor invoked on the piece that
  100. > piece of memory.  Why can't this be done?
  101.  
  102. Personally, I find the assignment operator almost exactly as
  103. "painful" to write as the copy constructor.  But if for some
  104. reason it is more painful to initialize objects in operator=
  105. than in the copy constructor, you could write operator= this way:
  106.     void A::operator=(const A& rhs)
  107.     {
  108.     if (this != &rhs) {
  109.         this->~A();
  110.         new (this) A(rhs);
  111.     }
  112.     }
  113.  
  114. But for two members, it's the same number of lines anyway :-)
  115. --
  116. Kevin J. Hopps                  e-mail: kjhopps@mmm.com
  117. 3M Company                      phone:  (612) 737-4643
  118. 3M Center, Bldg. 235-2D-57      fax:    (612) 737-2700
  119. St. Paul, MN 55144-1000         Opinions are my own.  I don't speak for 3M.
  120.     But 3M speaks for me -- I did not write the following line:
  121.  
  122. Opinions expressed herein are my own and may not represent those of 3M.
  123.